package log

import (
	"fmt"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"miomp-terminal-suite/backend/config"
	"miomp-terminal-suite/backend/global"
	"miomp-terminal-suite/backend/log"
	"os"
	"time"
)

var cfg *config.AppConfig
var mode string

func Init() {

	cfg = global.CONF

	mode = cfg.AppDetailConfig.Mode

	writeSyncer := getLogWriter(
		cfg.Filename,
		cfg.MaxSize,
		cfg.MaxBackUps,
		cfg.MaxAge,
	)

	level := new(zapcore.Level)
	err := level.UnmarshalText([]byte(cfg.Level))
	if err != nil {
		fmt.Println("日志配置错误")
	}
	var core zapcore.Core
	if mode == "dev" {
		core = zapcore.NewTee(
			zapcore.NewCore(getDevEncoder(), writeSyncer, level),
			zapcore.NewCore(getDevEncoder(), zapcore.Lock(os.Stdout), zapcore.DebugLevel),
		)
	} else {
		core = zapcore.NewCore(getProductEncoder(), writeSyncer, level)
	}

	lg := zap.New(core, zap.AddCaller())
	zap.ReplaceGlobals(lg)
	log.LOG = zap.L()
	log.U = &log.Utils{}
	defer func(LOG *zap.Logger) {
		err := LOG.Sync()
		if err != nil {
			fmt.Println("日志配置错误")
			fmt.Println(err.Error())
		}
	}(lg)
}

func getDevEncoder() zapcore.Encoder {
	return zapcore.NewConsoleEncoder(
		zapcore.EncoderConfig{
			TimeKey:        "ts",
			LevelKey:       "level",
			NameKey:        "logger",
			CallerKey:      "caller_line",
			FunctionKey:    zapcore.OmitKey,
			MessageKey:     "msg",
			StacktraceKey:  "stacktrace",
			LineEnding:     zapcore.DefaultLineEnding,
			EncodeLevel:    cEncodeLevel,
			EncodeTime:     cEncodeTime,
			EncodeDuration: zapcore.MillisDurationEncoder,
			EncodeCaller:   cEncodeCaller,
		})
}

func getProductEncoder() zapcore.Encoder {
	return zapcore.NewConsoleEncoder(
		zapcore.EncoderConfig{
			TimeKey:        "ts",
			LevelKey:       "level",
			NameKey:        "logger",
			CallerKey:      "caller_line",
			FunctionKey:    zapcore.OmitKey,
			MessageKey:     "msg",
			StacktraceKey:  "stacktrace",
			LineEnding:     zapcore.DefaultLineEnding,
			EncodeLevel:    cEncodeLevel,
			EncodeTime:     cEncodeTime,
			EncodeDuration: zapcore.MillisDurationEncoder,
			EncodeCaller:   cEncodeCaller,
		})
}

func getLogWriter(filename string, maxSize int, maxBackups int, maxAge int) zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   filename,
		MaxSize:    maxSize,
		MaxBackups: maxBackups,
		MaxAge:     maxAge,
		Compress:   true,
	}
	return zapcore.AddSync(lumberJackLogger)
}

// cEncodeLevel 自定义日志级别显示
func cEncodeLevel(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("| " + level.CapitalString() + " |")
}

// cEncodeTime 自定义时间格式显示
func cEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(t.Format("2006-01-02 15:04:05.000") + " |")
}

// cEncodeCaller 自定义行号显示
func cEncodeCaller(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("[" + caller.TrimmedPath() + "] |")
}
